/**
 * Copyright (c) 2011 Tomi Paananen.
 *
 * Part of Quick Gestures engine library.
 */

// Own header
#include "featureextractor.h"

// qgengine includes
#include "gesture.h"
#include "gestureprocessor.h"
#include "qgcommon.h"
#include "qgutils.h"
#include "qgtrace.h"

// Namespace declaration
using namespace QGEngine;


/*!
  \class FeatureExtractor
  \brief Extracts features from the given raw gesture and forms a normalized
         gesture.
*/


/*!
  Constructor.
*/
FeatureExtractor::FeatureExtractor(QObject *parent /* = 0 */)
    : QObject(parent),
      m_processor(0),
      m_gesturePointCount(GesturePointCount),
      m_gestureScaleFactor(GestureScaleFactor)
{
    m_processor = new GestureProcessor();
}


/*!
  Destructor.
*/
FeatureExtractor::~FeatureExtractor()
{
    delete m_processor;
}


/*!
  Sets \a count as the gesture point count for normalization.
*/
void FeatureExtractor::setGesturePointCount(int count)
{
    DEBUG_INFO(count);

    if (count > 1) {
        m_gesturePointCount = count;
    }
}


/*!
  Sets \a scaleFactor as the gesture scale factor value for normalization.
*/
void FeatureExtractor::setGestureScaleFactor(quint32 scaleFactor)
{
    DEBUG_INFO(scaleFactor);

    if (scaleFactor > 1) {
        m_gestureScaleFactor = scaleFactor;
    }
}


/*!
  Processes (normalizes) \a gesture. Returns QGEngine::NoError if the gesture
  was successfully processed, an error code otherwise. In addition, the method
  emits the signal gestureProcessed(Gesture*) if successful.
*/
int FeatureExtractor::processGesture(Gesture *gesture)
{
    DEBUG_POINT;

    if (!gesture) {
        DEBUG_INFO("Invalid argument: NULL pointer!");
        return InvalidArgument;
    }

    // Get the gesture points.
    PointList points = gesture->modifiablePoints();

    if (points.count() != m_gesturePointCount) {
        // Depending on the case increase/decrease the point count to match
        // the value defined in GesturePointCount.
        points = m_processor->distributePointsEvenly(points, m_gesturePointCount);
    }

    // Get the minimum and maximum points of the gesture.
    int minX(0);
    int minY(0);
    int maxX(0);
    int maxY(0);
    QGUtils::getMinMaxXY(points, minX, minY, maxX, maxY);

    if (minX != 0 || minY != 0) {
        // Move the gesture so that the coordinates of its top-left corner
        // are [0, 0].
        m_processor->moveTopLeft(points);
    }

    // Get the length of the greater side of the imaginary rectangle bouding
    // the gesture points.
    quint32 maxLength((qAbs(maxX - minX) >= qAbs(maxY - minY)) ?
                          qAbs(maxX - minX) : qAbs(maxY - minY));

    if (maxLength != m_gestureScaleFactor) {
        // Scale the gesture.
        m_processor->scale(points, m_gestureScaleFactor);
    }

    gesture->setPoints(points);

    emit gestureProcessed(gesture);
    return NoError;
}


/*!
  For convenience. Processes every gesture in \a gestureSet. Returns
  QGEngine::NoError if successful, an error code otherwise.
*/
int FeatureExtractor::processGestureSet(QList<Gesture*> &gestureSet)
{
    const int count(gestureSet.count());
    int error(NoError);

    for (int i = 0; i < count; ++i) {
        error = processGesture(gestureSet[i]);

        if (error != NoError) {
            return error;
        }
    }

    return error;
}


// End of file.
